#!/usr/bin/python
import os
import sys
import MySQLdb
import string
import time

def getResourceLeft(): 
   return 0


def isDigtal(myNum):
    nums = string.digits
    if type(myNum) is not str:
        return False
    else:
        for temp in myNum:
            if temp not in nums:
                return False
        return True
        
def checkParameter(conn):
    global mtid
    global stid
    global sncnt
    
    if not conn:
        print "Can not connect to database, Fail!"
        return -1
    paraCnt=len(sys.argv)
    if paraCnt != 3:
        return 0
    para=sys.argv[1]
    if para != "-mpi":
        return 0
    para = sys.argv[2]
    master_type,salve_type,salve_cnt=para.split(',')
    mtname,mtid=master_type.split('=')
    stname,stid=salve_type.split('=')
    snname,sncnt=salve_cnt.split('=')
    if mtname != "mtype" or stname != "stype" or snname != "snum":  
        return 0
    if not isDigtal(mtid):
        return 0
    if not isDigtal(stid):
        return 0
    if not isDigtal(sncnt):
        return 0
    flag = conn.execute("select vm_id from vm_info where vm_id = " + mtid);
    if flag == 0:
        print "No Master Node VM ", mtid 
        return 0
    flag = conn.execute("select vm_id from vm_info where vm_id = " + stid);
    if flag == 0:
        print "No Salve Node VM ", stid
        return 0
    return 1

def startVm(ip,mem,vcpu,mac,base_img_path,name,vm_img,vm_hvm):
    #print "ip=",ip 
    os.popen("ssh root@"+ip+" qcow-create 2000 "+vm_img+" " + base_img_path)
    #print "ssh root@"+ip+" qcow-create 2000 "+vm_img+" " + base_img_path
    
    str_hvm = "import os, re\n" + \
        "arch = os.uname()[4]\n" + \
        "if re.search('64', arch):\n" + \
    "    arch_libdir = 'lib64'\n" + \
    "else:\n" + \
    "    arch_libdir = 'lib'\n" + \
    "kernel = \"/usr/lib/xen/boot/hvmloader\"\n" + \
    "builder='hvm'\n" + \
    "memory = "+ str(mem) +"\n" + \
    "shadow_memory = 8\n" + \
    "name = \"" + name +"\"\n" + \
    "vcpus="+str(vcpu)+"\n" + \
    "vif = [ 'type=ioemu, mac="+mac+", bridge=xenbr0' ]\n" + \
    "disk = [ 'file:" + vm_img +",ioemu:hda,w' ]\n" + \
    "device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm'\n" + \
    "boot='c'\n" + \
    "sdl=0\n" + \
    "vnc=1\n" + \
    "vnclisten=\"0.0.0.0\"\n" + \
    "stdvga=0\n" + \
    "serial='pty'"

    p_str = open(vm_hvm,"w")
    p_str.write(str_hvm)
    p_str.close()
    #os.popen("scp "+vm_hvm+" root@"+ip+":"+vm_hvm)
    os.popen("ssh root@"+ip+" xm create "+vm_hvm)
    out = os.popen("ssh root@"+ip+" xm domid "+name)
    return out.read()
     
    #print "scp "+vm_hvm+" root@"+ip+":"+vm_hvm
    #print "ssh root@"+ip+" xm create "+vm_hvm
    return 0

def mpiJobs(conn):
    global mtid
    global stid
    global sncnt
    cnt_vm = int(sncnt)
    place=[]
    list_used_mem=[]
    list_used_vcpu=[]
    list_total_mem=[]
    list_total_vcpu=[]  
    list_ip=[]
    
    cnt_pm = conn.execute("select resource_id,ip,mem,cpu from resource_description")
    rows = conn.fetchall() 
    index=0
    while index <= cnt_pm:
        list_used_mem.append(0)
        list_used_vcpu.append(0)
        list_total_mem.append(0)
        list_total_vcpu.append(0)
        list_ip.append("")
        index += 1

    for temp in rows:
        list_total_mem[temp[0]] = temp[2]
        list_total_vcpu[temp[0]] = temp[3]
        list_ip[temp[0]] = temp[1]
     
    conn.execute("select resource_description.resource_id, vm_info.mem, vm_info.cpu " +\
                    "from resource_description,jobs,job_resource,vm_info " + \
                    "where jobs.status='running' and jobs.job_id=job_resource.job_id and job_resource.vm_id=vm_info.vm_id")
    rows=conn.fetchall()
    for temp in rows:
        list_used_mem[temp[0]] += temp[1]
        list_used_vcpu[temp[0]] += temp[2]
    
    conn.execute("select mem,cpu,img_store_path from vm_info where vm_id = "+mtid)
    rows=conn.fetchall()
    m_mem=rows[0][0]
    m_vcpu=rows[0][1]
    m_img_path=rows[0][2]
    
    conn.execute("select mem,cpu,img_store_path from vm_info where vm_id = "+stid)
    rows=conn.fetchall()
    s_mem=rows[0][0]
    s_vcpu=rows[0][1]
    s_img_path=rows[0][2]
     
    index=1
    while index <= cnt_pm:
        if list_used_mem[index] + m_mem < list_total_mem[index] - 256:
            list_used_mem[index] += m_mem
            place.append(index)
            break
        index += 1
    if index > cnt_pm:
        print "1 - Not Enough Resource,Fail!"
        return 0
    index1 = 1
    while index1 <= cnt_vm:
        index = 1
        while index <= cnt_pm:
            if list_used_mem[index] + s_mem < list_total_mem[index] - 256:
                list_used_mem[index] += s_mem
                place.append(index)
                break 
            index += 1
        if index > cnt_pm:
            break
        index1 += 1
    if index1 < cnt_vm:
        print "2 - Not Enough Resource,Fail!"
        return 0
    
    total_ip = conn.execute("select mac, ip from macaddress where used = 'n'") 
    if total_ip < cnt_vm+1:
        print "3 - Not Enough IP Resource,Fail!"
        return 0
    
    rows=conn.fetchall()
    vm_ip=[]
    vm_mac=[]
    index = 0
    while index <= cnt_vm:
        vm_ip.append(rows[index][1])
        vm_mac.append(rows[index][0])   
        index += 1
    
    vm_name=str(time.time())
    tmp=vm_name.split('.')
    #print "time: ", tmp[0],tmp[1]
    vm_name=string.join(tmp,'')
    
    mac=vm_mac[0]
    ip=str(list_ip[place[0]])
    mem=m_mem
    vcpu=m_vcpu
    base_img=m_img_path
    vm_img="/tmp/mpiPaaS/"+vm_name+".img"
    vm_hvm="/tmp/mpiPaaS/"+vm_name+".hvm"
    
    list_uuid=[]
    list_path_img=[]
    list_path_hvm=[]
    
    uuid = startVm(ip,mem,vcpu,mac,base_img,vm_name,vm_img,vm_hvm)    
    list_uuid.append(uuid)
    list_path_img.append(vm_img)
    list_path_hvm.append(vm_hvm)
    
    index=1
    while index <= cnt_vm:
        vm_name=str(time.time())
        tmp=vm_name.split('.')
        tmp.append(str(index))
        vm_name= string.join(tmp,'')
        mac=vm_mac[index]
        ip=str(list_ip[place[index]])
        mem=s_mem
        vcpu=s_vcpu
        base_img=s_img_path
        vm_img="/tmp/mpiPaaS/"+vm_name+".img"
        vm_hvm="/tmp/mpiPaaS/"+vm_name+".hvm"
        uuid = startVm(ip,mem,vcpu,mac,base_img,vm_name,vm_img,vm_hvm)
        
        list_uuid.append(uuid)
        list_path_img.append(vm_img)
        list_path_hvm.append(vm_hvm)    
        
        index += 1

    temp = str(time.time()).split('.')
    startTime= temp[0]
    conn.execute("insert into jobs(user,status,start_time,end_time) values('root','running',"+startTime+",0)")
    conn.execute("select max(job_id) from jobs")
    rows=conn.fetchall()
    job_id=rows[0][0]
    
    index = 0
    while index <= cnt_vm:
        conn.execute("update macaddress set used='y' where mac = '" + vm_mac[index] +"'")
        index += 1
    conn.execute("insert into job_resource(job_id,resource_id,vm_id,vm_ip,vm_root_password) values("+str(job_id)+","+str(place[0])+","+mtid+",'"+vm_ip[0]+"','passw0rd')")     
    index = 1
    while index <= cnt_vm:
        conn.execute("insert into job_resource(job_id,resource_id,vm_id,vm_ip,vm_root_password) values("+str(job_id)+","+str(place[index])+","+stid+",'"+vm_ip[index]+"','passw0rd')")   
        index +=1
    
    index = 0
    while index <= cnt_vm:
        conn.execute("insert into vm_store(job_id,ip,img_path,hvm_path,vm_uuid) values("+str(job_id)+",'" + str(list_ip[place[index]])+ "','" +list_path_img[index]+ "','"+list_path_hvm[index]+"',"+str(list_uuid[index])+")")
        index += 1
    print "Job ID: ", job_id
mtid="0"
stid="0"
sncnt="0"
str_command="command format:\n" + \
"   cjob -mpi mtype=master_type_ID,stype=salve_type_ID,snum=salve_number\n" + \
"   For example: cjob -mpi mtype=2,stype=1,snum=2"

if __name__ == "__main__":
    connect=MySQLdb.connect(host="localhost",port=3306,user="root",passwd="passw0rd",db="cloud")
    conn=connect.cursor()
    print connect,conn
    flag = checkParameter(conn)
    if flag == -1:
        sys.exit(0)
    if flag == 0:
        print str_command
        sys.exit(0)
    mpiJobs(conn) 
    conn.close()
    connect.close()

